package com.hds.modules.sys.controller.base;

import com.hds.common.annotation.SysLog;
import com.hds.common.utils.PageUtils;
import com.hds.common.utils.R;
import com.hds.common.validator.Assert;
import com.hds.modules.app.entity.ActivationCodeEntity;
import com.hds.modules.app.enums.ActivateCode;
import com.hds.modules.app.enums.UserEnum;
import com.hds.modules.app.service.ActivationCodeService;
import com.hds.common.utils.ActivateCodeGenerator;
import com.hds.modules.app.utils.DateUtils;
import com.hds.modules.job.entity.ScheduleJobEntity;
import com.hds.modules.job.service.ScheduleJobService;
import com.hds.modules.sys.controller.AbstractController;
import com.hds.modules.sys.entity.base.SysCompanyEntity;
import com.hds.modules.sys.entity.base.SysMemberShipEntity;
import com.hds.modules.sys.entity.base.dto.ActivateDto;
import com.hds.modules.sys.service.base.SysCompanyService;
import com.hds.modules.sys.service.base.SysMemberShipService;
import com.hds.modules.sys.utils.ActivationCodeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author guonan
 * @Email guonan@yewcn.com
 * @Description
 * @Date 2018/6/11 12:15
 */
@RestController
@RequestMapping("/sys/activatecode")
public class SysActivationCodeController extends AbstractController {

    @Autowired
    private ActivationCodeService activationCodeService;

    @Autowired
    private SysCompanyService sysCompanyService;

    @Autowired
    private SysMemberShipService sysMemberShipService;

    @Autowired
    private ScheduleJobService scheduleJobService;


    /**
     * 激活码列表
     */
    @SysLog("激活码列表")
    @GetMapping("/list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = activationCodeService.queryPage(params);

        return R.ok().put("page", page);
    }

    /**
     * 删除激活码-使其失效
     * @param id
     * @return
     */
    @RequestMapping("/del/{id}")
    public R del(@PathVariable("id") Integer id){
        Assert.isNull(id,"id不能为空");

        ActivationCodeEntity code = activationCodeService.selectById(id);
        Assert.isNull(code,"未找到该激活码。");
        code.setStatus(ActivateCode.StatusEnum.EXPIRED.getStatus());
        boolean rst = activationCodeService.insertOrUpdate(code);

        return rst ? R.ok() : R.error("删除失败");
    }


    /**
     * 批量生成激活码
     * @param  code
     * @return
     */
    @SysLog("批量生成激活码")
    @PostMapping("/generate")
    public R generateCode(@RequestBody ActivateDto code){

        Assert.isNull(code, "请检查参数是否填写完整");
        Integer guarant = code.getGuarant();
        Integer period = code.getPeriod();
        Integer count = code.getCount();
        Integer companyId = code.getCompanyId();
        Integer levelId = code.getLevelId();

        Assert.isNull(count, "输入要生成的数量");
        Assert.isNull(companyId, "所属公司不能为空");
        Assert.isNull(levelId, "激活码等级不能为空");

        SysMemberShipEntity memberShip = sysMemberShipService.selectById(levelId);
        if(memberShip==null)return R.error("该会员等级不存在");
        Date guarantee = DateUtils.addMonths(new Date(), guarant); //激活码保质期

        if(memberShip.getLevel() == UserEnum.VipLevel.TOURIST.getLevel()){
           return R.error("不能生成游客等级的激活码");
        }

        Integer maxBatch = activationCodeService.queryMaxBatchByCompanyId(companyId); // 查询当前该公司已经生成第几批次
        Integer nextBatch = null;

        if(maxBatch==null){ // 本次生成的是该公司的第几批激活码
            nextBatch = 1;
        }else{
            nextBatch = maxBatch+1;
        }


        Long start = System.currentTimeMillis();
        List<ActivationCodeEntity> list = new ArrayList<>();
        SysCompanyEntity company = sysCompanyService.selectById(companyId);
        String codePrefix = null;
        //String cardPrefix = null;
        if(company != null){
            //cardPrefix = company.getCardPrefix();
            codePrefix = company.getCodePrefix();
        }

        String maxCardNo = activationCodeService.queryMaxCardNo(companyId);
        if(maxCardNo == null){
            maxCardNo = "00000000";
        }

        for (int i = 1; i <= count; i++){
            ActivationCodeEntity activationCode = new ActivationCodeEntity();

            activationCode.setCreateTime(new Date());
            activationCode.setCompanyId(companyId);
            activationCode.setGuarantee(guarantee);
            activationCode.setBatch(nextBatch);

            // 卡号组装
            activationCode.setCardNo(ActivationCodeUtil.long2NormalNumber(Integer.valueOf(maxCardNo) + i));
            activationCode.setLevelId(memberShip.getId());
            activationCode.setPeriod(period);
            activationCode.setActivationcode(codePrefix + ActivateCodeGenerator.genRandomNum());

            list.add(activationCode);
        }
        boolean rst = activationCodeService.insertOrUpdateBatch(list);
        if(rst){

            //创建定时器，过了保质期后该公司的这一批未激活的激活码全部失效 [要考虑到保质期内已经激活的激活码]
            //生成定时器 - [激活码超过保质期失效]
            generateJob(guarantee,"activateCodeTask",
                    "batchExpire",
                    companyId+"|"+nextBatch,
                    "该公司(id:"+companyId+")第"+nextBatch+"批次激活码已生成");
        }
        Long end = System.currentTimeMillis();
        return R.ok().desc("批量插入耗时："+ (end - start) +"毫秒"); //插入5000条数据大约耗时2346毫秒
    }



    /**
     * 生成定时器：激活码过期失效
     * @param date 过期时间
     * @param taskName
     * @param methodName
     * @param params
     * @param mark
     */
    public void generateJob(Date date, String taskName, String methodName, String params, String mark){
        String expiredYear = DateUtils.format(date, "yyyy");
        String expiredTimeFormat = DateUtils.format(date, "ss mm HH dd MM");
        String cron = expiredTimeFormat+" ? "+expiredYear;

        //创建定时器，过了保质期后该公司的这一批未激活的激活码全部失效 [要考虑到保质期内已经激活的激活码]
        ScheduleJobEntity scheduleJob = new ScheduleJobEntity();
        scheduleJob.setBeanName(taskName);
        scheduleJob.setCreateTime(new Date());
        scheduleJob.setCronExpression(cron); //cron表达式 例如:30 10 1 20 10 ? 2011
        scheduleJob.setMethodName(methodName);
        scheduleJob.setParams(params);//companyId+"|"+nextBatch
        scheduleJob.setRemark(mark); //"该公司(id:"+companyId+")第"+nextBatch+"批次激活码更新为过期状态-标记"
        scheduleJob.setStatus(0);

        //生成定时器
        scheduleJobService.save(scheduleJob);
    }









    /**
     * 激活码:批量生成/更新
     *
     * @param count - 生成数量
     * @param levelId - 激活码等级Id(1-注册会员,2-VIP会员卡，3-金卡会员)
     * @@param companyId - 所属公司id
     * @param period - 激活码服务年限[单位：年]
     */
    @SysLog("激活码生成")
    @PostMapping("/generateOrUpd")
    public R generateOrUpd(@RequestParam(name="count",required = true) Integer count,
                           @RequestParam(name="level", required = true) Integer levelId,
                           @RequestParam(name="companyId", required = true) Integer companyId,
                           @RequestParam(name="period",defaultValue = "1") Integer period){

        Assert.isNull(count, "count不能为空");
        Assert.isNull(companyId, "companyId不能为空");
        Assert.isNull(levelId, "level不能为空");

        SysMemberShipEntity memberShip = sysMemberShipService.selectById(levelId);
        if(memberShip==null)return R.error("该会员等级不存在");

        Long start = System.currentTimeMillis();
        List<ActivationCodeEntity> list = new ArrayList<>();

        SysCompanyEntity company = sysCompanyService.selectById(companyId);
        String codePrefix = null;
        String cardPrefix = null;
        if(company != null){
            cardPrefix = company.getCardPrefix();
            codePrefix = company.getCodePrefix();
        }

        String maxCardNo = activationCodeService.queryMaxCardNo(companyId);
        if(maxCardNo == null){
            maxCardNo = "000000";
        }
        System.out.println("maxCardNo:"+maxCardNo);
        for (int i = 1; i <= count; i++){
            ActivationCodeEntity activationCode = new ActivationCodeEntity();

            activationCode.setCreateTime(new Date());
            activationCode.setCompanyId(companyId);
            activationCode.setLevelId(memberShip.getId());
            // 卡号组装
            activationCode.setCardNo(cardPrefix + memberShip.getLevel() + ActivationCodeUtil.long2NormalNumber(Integer.valueOf(maxCardNo) + i));
            activationCode.setPeriod(period);
            activationCode.setActivationcode(codePrefix + ActivateCodeGenerator.genRandomNum());

            list.add(activationCode);
        }
        boolean rst = activationCodeService.insertOrUpdateBatch(list);
        Long end = System.currentTimeMillis();
        System.out.println("批量插入耗时："+ (end - start)); //插入5000条数据大约耗时2346毫秒

        return rst ? R.ok().desc("耗时"+(end - start)+"毫秒") : R.error();
    }

}
